package com.turing.post.antimoney.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;

import com.turing.post.antimoney.util.AlarmInfo;
import com.turing.post.antimoney.util.AlarmInfoDao;
import com.turing.post.antimoney.util.AlarmInfoDetail;
import com.turing.post.antimoney.util.AlarmInfoDetailDao;
import com.turing.post.antimoney.util.AlarmRule;
import com.turing.post.antimoney.util.AlarmRulesBusiness;
import com.turing.post.cardmanagement.util.ActivateCard;
import com.turing.post.cardmanagement.util.ActivateCardDao;
import com.turing.post.common.util.PCPSCommonDao;
import com.turing.post.organization.util.Merchant;
import com.turing.post.organization.util.MerchantDao;
import com.turing.post.organization.util.SaleBranch;
import com.turing.post.organization.util.SaleBranchDao;
import com.turing.post.salesmanage.util.OrganizeCustomDao;
import com.turing.post.salesmanage.util.PersonalCustomDao;
import com.turing.post.salesmanage.util.SaleOrder;
import com.turing.post.salesmanage.util.SaleOrderCardDetailDao;
import com.turing.post.salesmanage.util.SaleOrderDao;
import com.turing.post.transaction.util.MchAccDetail;
import com.turing.post.transaction.util.MchAccDetailDao;
import com.turing.post.transaction.util.MchTradDetail;
import com.turing.post.transaction.util.MchTradDetailDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;

/**
 * 规则 13 19： 对于同一个购卡主体，在同一POS交易一天超过1万元 N天，N元 zxp
 */
@Remote
@Local
@Stateless(mappedName = "antimoney.impl.AlarmRule13")
public class AlarmRule13 implements AlarmRulesBusiness {

	@EJB(mappedName = "common.impl.PCPSCommonDaoImpl")
	private PCPSCommonDao commonDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.ActivateCardDaoImpl")
	private ActivateCardDao activateCardDaoImpl;

	@EJB(mappedName = "transaction.impl.MchTradDetailDaoImpl")
	private MchTradDetailDao mchTradDetailDaoImpl;

	@EJB(mappedName = "antimoney.impl.AlarmInfoDaoImpl")
	private AlarmInfoDao alarmInfoDaoImpl;

	@EJB(mappedName = "antimoney.impl.AlarmInfoDetailDaoImpl")
	private AlarmInfoDetailDao alarmInfoDetailDaoImpl;

	@EJB(mappedName = "transaction.impl.MchAccDetailDaoImpl")
	private MchAccDetailDao mchAccDetailDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderCardDetailDaoImpl")
	private SaleOrderCardDetailDao saleOrderCardDetailDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderDaoImpl")
	private SaleOrderDao saleOrderDaoImpl;

	@EJB(mappedName = "organization.impl.SaleBranchDaoImpl")
	private SaleBranchDao saleBranchDaoImpl;

	@EJB(mappedName = "salesmanage.impl.PersonalCustomDaoImpl")
	private PersonalCustomDao personalCustomDaoImpl;

	@EJB(mappedName = "salesmanage.impl.OrganizeCustomDaoImpl")
	private OrganizeCustomDao organizeCustomDaoImpl;

	@EJB(mappedName = "organization.impl.MerchantDaoImpl")
	private MerchantDao merchantDaoImpl;

	/***************************************************************************
	 * 规则参数 第0个参数 天 第1个参数 元
	 * 
	 */
	@Override
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void runAlarmRules(String icNo, Date tranDate, AlarmRule alarmRule)
			throws PCPSApplicationException {
		// 有预警规则参数
		if (!PCPSUtil.isEmpty(alarmRule.getRuleParameter())) {
			int dayNum = 0;
			BigInteger amount = BigInteger.ZERO;
			try {
				String[] par = alarmRule.getRuleParameter().split(":");
				// 限制参数
				dayNum = Integer.parseInt(par[0]);
				amount = new BigInteger(par[1]).multiply(BigInteger
						.valueOf(100));
			} catch (Exception e) {
				PCPSUtil.Log("AlarmRules RuleParameter Error", e);
				return;
			}
			// 查询起始终止时间
			String startDate = PCPSUtil.getPackedYMDString2(tranDate);
			if (dayNum > 1) {
				startDate = PCPSUtil.BeforeNowDate(tranDate, 0 - (dayNum - 1));
			}
			String endDate = PCPSUtil.getPackedYMDString2(tranDate);
			// System.out.println("AlarmRule13 RuleParameter One：" + startDate
			// + " " + endDate + " Two：" + amount);
			PCPSUtil.Log("Start AlarmRule13 RuleParameter One：" + startDate
					+ " " + endDate + " Two：" + amount);
			// 终端号列表
			List<String> terminalNoList = mchTradDetailDaoImpl
					.getAlarmRule13OverTermimalNoList(icNo, amount, startDate,
							endDate);
			String merchantNo = "";
			Merchant merchant = null;
			if (terminalNoList != null && terminalNoList.size() > 0) {
				for (String terminalNo : terminalNoList) {
					merchantNo = mchTradDetailDaoImpl
							.getMerchantNoByTerminalNo(icNo, startDate,
									endDate, terminalNo);
					merchant = merchantDaoImpl
							.getMerchantByMerchantNo(merchantNo);
					dealMchTradDatailByTerminalNo(icNo, tranDate, merchant,
							terminalNo, startDate, endDate, amount, alarmRule);
				}
			}
		}
		// System.out.println("End AlarmRule13");
		PCPSUtil.Log("End AlarmRule13");
	}

	/**
	 * 处理满足条件的终端交易
	 * 
	 * @param icNo
	 * @param terminalNo
	 * @param startDate
	 * @param endDate
	 * @throws PCPSApplicationException
	 */
	@SuppressWarnings("unchecked")
	private void dealMchTradDatailByTerminalNo(String icNo, Date tranDate,
			Merchant merchant, String terminalNo, String startDate,
			String endDate, BigInteger amount, AlarmRule alarmRule)
			throws PCPSApplicationException {
		// 同一终端号下的交易明细
		List<MchTradDetail> mtdList = mchTradDetailDaoImpl
				.getAlarmRule13MchTradDetailListByCond(icNo, terminalNo,
						startDate, endDate);
		if (mtdList == null || mtdList.size() < 1) {
			return;
		}
		// 满足条件所有交易卡号列表
		HashMap<String, String> cardMp = new HashMap<String, String>();
		// 同一终端下所有交易数据
		List<MchAccDetail> allAccDetail = new ArrayList<MchAccDetail>();
		ActivateCard ac = null;
		for (MchTradDetail mtd : mtdList) {
			// 商户交易记帐明细信息列表
			List<MchAccDetail> mchAccDetailList = mchAccDetailDaoImpl
					.getAllMchAccDetailByTranSeqNo(mtd.getMerchantNo(), mtd
							.getTranDate(), mtd.getTranSeqNo());
			// 交易明细不为空时
			if (mchAccDetailList != null && mchAccDetailList.size() > 0) {
				for (MchAccDetail acc : mchAccDetailList) {
					// 后期可以优化，这里ac不可能为空
					ac = activateCardDaoImpl.getActivateCardByCardNo(acc
							.getCardNo());
					if (ac != null) {
						// 加入list
						allAccDetail.add(acc);
					}
					// map中存放卡号，卡顺序号
					if (!cardMp.containsKey(acc.getCardNo())) {
						if (ac != null) {
							cardMp.put(acc.getCardNo(), ac.getCardSeqNo());
						}
					}
				}
			}
		}
		// 购卡人map
		HashMap<String, String> buyerMap = new HashMap<String, String>();
		// 卡号与购卡人关联
		List<String[]> cardWithBuyer = new ArrayList<String[]>();
		// 根据卡号、卡序号获取购卡人信息
		if (cardMp.size() < 1) {
			return;
		}
		Iterator iter = cardMp.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			// 卡号
			String key = entry.getKey().toString();
			// 卡序号
			String val = entry.getValue().toString();
			// 根据卡号获取购卡人信息 0个人 1 单位
			String[] buyerArr = saleOrderCardDetailDaoImpl
					.getSaleOrderByCardSeqNo(val);
			if (buyerArr == null) {
				// 根据卡序号未找到购卡人信息，直接跳过
				continue;
			}
			// 个人
			if (!PCPSUtil.isEmpty(buyerArr[0])) {
				buyerMap.put(buyerArr[0], "");
				cardWithBuyer
						.add(new String[] { buyerArr[0], key, buyerArr[2] });
			} else if (!PCPSUtil.isEmpty(buyerArr[1])) {
				// 单位
				buyerMap.put(buyerArr[1], "");
				cardWithBuyer
						.add(new String[] { buyerArr[1], key, buyerArr[2] });
			}
		}
		// 判断卡是否归属同一购卡人
		if (buyerMap.size() < 1) {
			return;
		}
		List<String> list = new ArrayList<String>();
		Iterator it = buyerMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			// 购卡人
			String key = entry.getKey().toString();
			list = getAllBuyerCardByBuyer(cardWithBuyer, key, allAccDetail,
					amount);
			// 满足风险的卡号列表
			if (list != null && list.size() > 0) {
				HashMap<String, String> saleOrderIdMap = getOwnerBuySaleOrderIdList(
						key, cardWithBuyer);
				releaseAlarm(icNo, tranDate, merchant, key, saleOrderIdMap,
						allAccDetail, list, alarmRule);
			}
		}
	}

	/**
	 * @param key
	 *            购卡人
	 * @param cardWithBuyer
	 *            0 够卡人 1 卡号 2 销售单号
	 * @return
	 */
	private HashMap<String, String> getOwnerBuySaleOrderIdList(String key,
			List<String[]> cardWithBuyer) {
		HashMap<String, String> map = new HashMap<String, String>();
		if (cardWithBuyer != null && cardWithBuyer.size() > 0) {
			// 0购卡人 1 销售单
			for (String[] s : cardWithBuyer) {
				// 同一购卡人
				if (key.equals(s[0])) {
					map.put(s[2], "");
				}
			}
		}
		return map;
	}

	/**
	 * 根据购卡人查询该购卡人下所有卡
	 * 
	 * @param cardWithBuyer
	 * @param key
	 */
	private List<String> getAllBuyerCardByBuyer(List<String[]> cardWithBuyer,
			String key, List<MchAccDetail> accDetailList, BigInteger amount) {
		if (cardWithBuyer == null || cardWithBuyer.size() < 1
				|| accDetailList == null || accDetailList.size() < 1) {
			return null;
		}
		// 同一购卡人下所有卡
		List<String> result = new ArrayList<String>();
		BigInteger allAmount = BigInteger.ZERO;
		// 不会含重复卡号
		for (String[] st : cardWithBuyer) {
			if (key.equals(st[0])) {
				// 卡号
				result.add(st[1]);
				// 卡销售金额是否超过设定金额
				for (MchAccDetail acc : accDetailList) {
					if (acc.getCardNo().equals(st[1])) {
						allAmount = allAmount.add(acc.getPaidAmount());
					}
				}
			}
		}
		// 同一购卡人同一POS消费大于设置金额
		if (allAmount.compareTo(amount) > 0) {
			return result;
		} else {
			return null;
		}
	}

	/**
	 * 发布风险信息
	 * 
	 * @param icNo
	 *            发卡商号
	 * @param key
	 *            购卡人
	 * @param buyerSaleOrderList
	 *            0购卡人 1销售单编号
	 * @param allAccDetail
	 *            交易数据列表
	 * @param cardNoList
	 *            预警交易卡号
	 * @param alarmRule
	 *            预警规则
	 * @throws PCPSApplicationException
	 */
	private void releaseAlarm(String icNo, Date tranDate, Merchant merchant,
			String key, HashMap<String, String> saleOrderIdMap,
			List<MchAccDetail> allAccDetail, List<String> cardNoList,
			AlarmRule alarmRule) throws PCPSApplicationException {
		List<MchAccDetail> insertAcc = new ArrayList<MchAccDetail>();
		if (allAccDetail != null && allAccDetail.size() > 0
				&& cardNoList != null && cardNoList.size() > 0) {
			for (MchAccDetail acc : allAccDetail) {
				for (String cardNo : cardNoList) {
					if (acc.getCardNo().equals(cardNo)) {
						insertAcc.add(acc);
					}
				}
			}
		}
		if (insertAcc == null || insertAcc.size() < 1) {
			return;
		}
		// 销售单
		insertSaleOrderAlarmInfoAndDetail(icNo, key, saleOrderIdMap, alarmRule);

		AlarmInfo alarmInfo = new AlarmInfo();
		alarmInfo.setAlarmRuleId(alarmRule.getAlarmRuleId());
		alarmInfo.setIssueCompanyNo(icNo);

		alarmInfo.setBranchNo(merchant.getMerchantNo());
		alarmInfo.setBranchName(merchant.getMerchantName());

		alarmInfo.setAlarmTime(commonDaoImpl.getDatabaseSysTime());
		alarmInfo.setRiskCustomName(merchant.getMerchantName());// 风险客户名称

		alarmInfo.setAlarmReason(alarmRule.getAlarmRuleDesc());
		alarmInfo.setDealStatus(AlarmInfo.ALARMINFO_DEALSTATUS_UNTREATED);
		BigInteger alarmInfoId = alarmInfoDaoImpl.getMaxAlarmInfoId();
		alarmInfo.setAlarmInfoId(alarmInfoId);
		// 插入预警信息
		alarmInfoDaoImpl.insertAlarmInfo(alarmInfo);
		int a = 0;
		for (MchAccDetail acc : insertAcc) {
			AlarmInfoDetail alarmInfoDetail = new AlarmInfoDetail();
			alarmInfoDetail.setAlarmInfoId(alarmInfoId);
			alarmInfoDetail.setSeqNo(a);
			alarmInfoDetail
					.setBusinessType(AlarmInfoDetail.ALARMINFODETAIL_BUSINESSTYPE_TRADDETAIL);
			alarmInfoDetail.setMerchantNo(acc.getMerchantNo());
			alarmInfoDetail.setTranDate(acc.getTranDate());
			alarmInfoDetail.setTranSeqNo(acc.getTranSeqNo());
			alarmInfoDetailDaoImpl.insertAlarmInfoDetail(alarmInfoDetail);
			a++;
		}
	}

	@SuppressWarnings("unchecked")
	private void insertSaleOrderAlarmInfoAndDetail(String icNo, String key,
			HashMap<String, String> saleOrderIdMap, AlarmRule alarmRule)
			throws PCPSApplicationException {
		if (saleOrderIdMap == null || saleOrderIdMap.size() < 1) {
			return;
		}
		SaleOrder so = null;
		String customName = "";

		Iterator it = saleOrderIdMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			// 销售单号
			BigInteger saleOrderId = new BigInteger(entry.getKey().toString());

			so = saleOrderDaoImpl.getSaleOrderBySaleOrderId(saleOrderId);
			AlarmInfo alarmInfo = new AlarmInfo();
			SaleBranch saleBranch = saleBranchDaoImpl
					.getSaleBranchBySaleBranchNo(so.getSaleBranchNo());
			alarmInfo.setAlarmRuleId(alarmRule.getAlarmRuleId());
			alarmInfo.setIssueCompanyNo(icNo);

			alarmInfo.setBranchNo(so.getSaleBranchNo());
			alarmInfo.setBranchName(saleBranch.getSaleBranchName());

			alarmInfo.setAlarmTime(commonDaoImpl.getDatabaseSysTime());

			if (so.getPersonalBuyerId() != null) {
				customName = personalCustomDaoImpl
						.getPersonalCustomByPersonalId(so.getPersonalBuyerId())
						.getName();
			} else if (so.getOrganizeBuyerId() != null) {
				customName = organizeCustomDaoImpl
						.getOrganizeCustomByOrganizeId(so.getOrganizeBuyerId())
						.getFullName();
			}

			alarmInfo.setRiskCustomName(customName);// 风险客户名称
			// 个人、单位名称
			alarmInfo.setAlarmReason(alarmRule.getAlarmRuleDesc());
			alarmInfo.setDealStatus(AlarmInfo.ALARMINFO_DEALSTATUS_UNTREATED);
			BigInteger alarmInfoId = alarmInfoDaoImpl.getMaxAlarmInfoId();
			alarmInfo.setAlarmInfoId(alarmInfoId);
			// 插入预警信息
			alarmInfoDaoImpl.insertAlarmInfo(alarmInfo);

			AlarmInfoDetail alarmInfoDetail = new AlarmInfoDetail();
			alarmInfoDetail.setAlarmInfoId(alarmInfoId);
			alarmInfoDetail.setSeqNo(0);
			alarmInfoDetail.setBusinessOrderId(so.getSaleOrderId());
			alarmInfoDetail
					.setBusinessType(AlarmInfoDetail.ALARMINFODETAIL_BUSINESSTYPE_SALEORDER);
			alarmInfoDetailDaoImpl.insertAlarmInfoDetail(alarmInfoDetail);
		}
	}
}
